angular.module('zixys.services',[])

    .factory('newOutputNode',['$rootScope', function ($rootScope) {
        var wrapper = $rootScope.$contentWrapper.parent().find('.zixys-style');

        return function(){
            return $('<style></style>').appendTo(wrapper);
        }
    }])

    .factory('zxNodes',[function(){
        var zxNodes = {
            nodes : {},
            selected : null
        }
        console.log(zxNodes);
        return zxNodes;
    }])

    .factory('zixysNode', ['nodeDeployer', 'newOutputNode', 'zxNodes', function (nodeDeployer, newOutputNode, zxNodes) {

        function zxNode() {
            this.selector = null;
            this.data = {};
            this.deployed = {};
            this.nodes = null;
            this.outputNode = null;
            this.isBroken = false;

        }

        zxNode.prototype.hasSelector = function (selector) {
            this.selector = selector;
            return this;
        }

        zxNode.prototype.setData = function (subset,data) {
            if(!subset) return;
            this.data[subset] = data;
            this.outputNode.html( nodeDeployer(this,subset));
            return this;
        }

        zxNode.prototype.hasNodes = function (data){
            this.nodes = data;

            this.isBroken = (data.length === 0);
            this.hasOneNode = (data.length === 1);
            this.hasManyNodes = (data.length > 1);

            return this;
        }

        zxNode.prototype.hasOutputNode = function (outputNode){
            this.outputNode = outputNode;
            return this;
        }

        zxNode.prototype.getNodes = function () {
            return this.nodes;
        }
        zxNode.prototype.getData = function(){
            return this.data;
        }
        zxNode.prototype.getSelector = function(){
            return this.selector;
        }

        zxNode.prototype.$_delete = function() {
            this.outputNode.remove();
            this.data = null;
            delete zxNodes.nodes[this.selector];
        }

        return function(selector) {
            if(!zxNodes.nodes[selector]){
                zxNodes.nodes[selector] = new zxNode().hasSelector(selector).hasOutputNode(newOutputNode());
            }
            zxNodes.selected = zxNodes.nodes[selector];
            return zxNodes.selected;
        }

    }])

    .service('style', [function(){

        this.set = function (selector, subset, subsetData) {

        }

        this.load = function (selector, subset) {

        }

    }])

    .service('Colors',function(){
        var self = this;

        this.HexToRGB = function(hex) {
            var hex = parseInt(((hex.indexOf('#') > -1) ? hex.substring(1) : hex), 16);
            return {
                r: hex >> 16, 
                g: (hex & 0x00FF00) >> 8, 
                b: (hex & 0x0000FF)
            };
        };
                
        this.RGBToHex = function(rgb) {
            function toHex(input) {
                if(input.toString(16).length<2){
                    return '0'+input.toString(16);
                }
                return input.toString(16);
            }
            return toHex(rgb.r)+toHex(rgb.g)+toHex(rgb.b);
        };
        
        this.parseRGB = function(input){
            var color = input.match(/\((.+)\)/)[1].split(',');
            return {
                rgb : {
                    r : parseInt(color[0]),
                    g : parseInt(color[1]),
                    b : parseInt(color[2])
                },
                alpha : 100

            };
        }

        this.parseRGBA = function(input){
            var color = input.match(/\((.+)\)/)[1].split(','),
                alpha = color.pop();
            return {
                rgb : {
                    r : parseInt(color[0]),
                    g : parseInt(color[1]),
                    b : parseInt(color[2])
                },
                alpha : parseInt(alpha)*100
            };
        }

        this.parseHEX = function(input){
            input = input.match(/(\w+)/gi);
            return {
                rgb:this.HexToRGB(input[0]),
                alpha:100
            };
        }

        this.parseColor = function(color){
            if(color.match('#')){
                //hex color
                return this.parseHEX(color);
            }else 
            if(color.match('rgba')){
                //rgba
                return this.parseRGBA(color);
            }else
            if(color.match('rgb')){
                //rgb
                return this.parseRGB(color);
            }
        };

        this.parseColorStop = function (string) {
            string = $.trim(string);
            var tmp = string.split(' '),
                color = tmp[0],
                pos = parseInt(tmp[1]);

            return {
                color : this.parseColor(color),
                position : pos
            }
        }

        this.stringifyColor = function(color){
            return 'rgba( '+
                        color.rgb.r+', '+
                        color.rgb.g+', '+
                        color.rgb.b+', '+
                        parseInt(color.alpha)/100+
                    ')';
        }

        this.getColor = function(color){
            var rgb;
            switch(color)
            {
                case 'black':
                    rgb = {r:0,g:0,b:0}
                    break;
                case 'white':
                    rgb = {r:255,g:255,b:255}
                    break;
                case 'grey':
                    rgb = {r:204,g:204,b:204}
                    break;
                default:
                    rgb = {r:255,g:255,b:255}
            }

            return {
                rgb : rgb,
                alpha : 100
            }
        }
        
    })

    .service('selectorTools',[function(){

        this.options = {
            class : true,
            id : true,
            tag : true
        };

        this.resolveCssSelector = function(element) {
            var classNames = '';
            var elementSelector = '';

            if(this.options.tag && element[0].tagName){
                elementSelector = elementSelector + element[0].tagName.toLowerCase();
            }
            if(this.options.id && element.attr('id')){
                elementSelector = elementSelector + '#' + element.attr('id');
            }
            if(this.options.class && element.attr('class')){
                classNames = element.attr('class');
                classNames = classNames.replace(/(\s+(zixys-hovered-item)|(zixys-hovered-item))/g,'');
                classNames = classNames.replace(/\s+/g,'.');
                if(classNames){
                    elementSelector = elementSelector +'.'+classNames;
                }
            }
            return elementSelector;
        }

    }])

    .service('CssDefaults',[function(){

        this.predefined = {
            //Text
            'textAlign' : ['left','right','center', 'justify', 'inherit'],
            'textDecoration' : ['none', 'underline', 'overline' ,'line-through', 'inherit' ],
            'textOverflow' : ['clip', 'ellipsis', 'inherit'],
            'textTransform' : ['none', 'capitalize', 'uppercase', 'lowercase','inherit'],

            //Font
            'fontVariant' : ['normal', 'small-caps','inherit'],
            'fontWeight' : ['normal', 'bold','bolder','lighter','inherit'],
            'fontStyle' : ['normal', 'italic','oblique', 'inherit']
        }

    }])

    .service('renderRules',['$interpolate', 'Colors', function ($interpolate, Colors) {

        this.corners = function(data){



        };

        this.shadow = function(data){
            if(data === 'clean') return '';

            var codeline = '';

            for (var i=0; i<data.length; i++){
                codeline = codeline+
                    data[i].left+'px '+
                    data[i].top+'px '+
                    data[i].blur+'px '+
                    data[i].size+'px '+
                    Colors.stringifyColor(data[i].color)+
                    (data[i].inner? 'inset' : '')+
                    (i!=data.length-1? ', ': '' );
            }

            return '-moz-box-shadow: '+codeline+';'+ /* Firefox */
                    '-webkit-box-shadow: '+codeline+';'+ /* Safari, Chrome */
                    'box-shadow: '+codeline+';'; /* CSS3 */
        }

        this.font = function(data){
            if(data === 'clean') return '';
            var output = '';
            output = output +
                        //text
                        (data.textAlign?'text-align:'+data.textAlign+';':'')+
                        (data.textDecoration?'text-decoration:'+data.textDecoration+';':'')+
                        (data.textOverflow?'text-overflow:'+data.textOverflow+';':'')+
                        (data.textTransform?'text-transform:'+data.textTransform+';':'')+
                        //font
                        (data.fontWeight?'font-weight:'+data.fontWeight+';':'')+
                        (data.fontVariant?'font-variant:'+data.fontVariant+';':'')+
                        (data.fontStyle?'font-style:'+data.fontStyle+';':'')+
                        (data.fontFamily?'font-family:'+data.fontFamily+';':'')+
                        (data.fontSize?'font-size:'+data.fontSize+'px;':'')+
                        (data.lineHeight?'line-height:'+data.lineHeight+'px;':'')+
                        (data.color?'color:'+Colors.stringifyColor(data.color)+';':'');
            if(data.fontUrl){
                output = data.fontUrl+output;
            }

            return output;
        }

        this.transform2d = function(){

            return '';
        }

        this.gradient = function (data) {

            var codeLine = '',
                statements = ['linear-gradient','-o-linear-gradient','-moz-linear-gradient','-webkit-linear-gradient','-ms-linear-gradient'],
                values = [], output = [], tmpGradent, tmpMarkers;
            //(dist+(gr.markers[i].getPos()*length)/100)
            //r = dist; c = length;
            //var codeLine = (alpha)+'deg, #'+$menu.firstColor.val()+' '+r+'px,'+markerColors+' #'+$menu.secondColor.val()+' '+(r+c)+'px';

            for (var i = 0; i<data.length; i++) {
                tmpGradent = data[i];
                tmpMarkers = data[i].markers;
                codeLine = codeLine + tmpGradent.angle + 'deg, ';
                if(tmpGradent.isModeAuto) {
                    for (var j=0; j<tmpMarkers.length; j++) {
                        codeLine = codeLine + Colors.stringifyColor(tmpMarkers[j].color)+ ' '+tmpMarkers[j].position+'%' + (j<tmpMarkers.length-1? ',':'');
                    }
                } else {
                    for (var j=0; j<tmpMarkers.length; j++) {
                        codeLine = codeLine + Colors.stringifyColor(tmpMarkers[j].color)+ ' '+(tmpGradent.distance + (tmpMarkers[j].position * tmpGradent.length)/100 )+'px' + (j<tmpMarkers.length-1? ',':'');
                    }
                }
                values.push(codeLine);
                codeLine = '';
            }
            codeLine = '';
            for (var i = 0; i<statements.length; i++){
                for (var j = 0; j<values.length; j++){
                    codeLine =codeLine + statements[i] + '('+values[j]+')'+( (j==values.length-1) ? '' : ',' );
                }
                output.push(codeLine);
                codeLine = '';
            }
            return output;
        }

    }])

    .factory('cssCompiler',['renderRules', function(renderRules){
        return function(data) {
            var output = '', gradient = '', background = '';

            if(data['corners']){
                output = output + renderRules.corners(data['corners']);
            }

            if(data['shadow']){
                output = output + renderRules.shadow(data['shadow']);
            }

            if(data['transform2d']){
                output = output + renderRules.transform2d(data['transform2d']);
            }

            if(data['font']){
                output = output + renderRules.font(data['font']);
            }

            if(data['gradient']){
                gradient = renderRules.gradient(data['gradient']);
            }

            if(gradient.length>0){

                for(var i = 0; i<gradient.length; i++){
                    if(gradient[i]){
                        output = output + 'background-image:' + gradient[i] +';';
                    }
                }
            }

            return output;
        }

    }])

    .factory('cssDeployer',['cssCompiler','nodeDeployer', function(cssCompiler, nodeDeployer) {
        return function(zxNode) {
            //return zxNode.selector + ' {' +cssCompiler(zxNode.data) +'}';
            return nodeDeployer(zxNode);
        }
    }])

    .service('compilers',function(){
        this.definedProperty = {};
        this.multipleProperty = {};
        this.customStructured = {};
    })

    .factory('compileDeployer',[function(){
        return function(zxNode,compiler){

        }
    }])

    .factory('nodeDeployer',['compilers', 'compileDeployer', function (compilers) {

        function definedPropertyCompiler(zxNode,compilerName) {

            var compiler = compilers.definedProperty[compilerName];
            var property = compiler.property;

            if (!zxNode.deployed[property]) { zxNode.deployed[property] = {} };

            if (!zxNode.deployed[property][compilerName]) {
                zxNode.deployed[property][compilerName] = {
                    value : compiler.compile(zxNode.data[compilerName]),
                    type : compiler.export
                }
            }
        }



        return function (zxNode,compilerName) {

            definedPropertyCompiler(zxNode,compilerName);

            console.log(zxNode);
            return '';
        }
    }])

    .factory('registerCompiler',['compilers',function(compilers){

        return function (compileObject) {
            var compilerKey = compileObject.name,
                property = compileObject.property;

            if (property) {

                //compiler returns defined property
                if (!compilers.definedProperty[compilerKey]) {
                    compilers.definedProperty[compilerKey] = compileObject;
                }
                //compilers.definedProperty[compilerKey].push(compileObject);

            } else {
                //compiler returns multiple properties
                if (!compilers.multipleProperty[compilerKey]) {
                    compilers.multipleProperty[compilerKey] = [];
                }
                compilers.multipleProperty[compilerKey].push(compileObject);
            }

            console.log(compilers);
        }
    }]);






;